package com.mdb.open.trade.facade;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.mdb.bc.api.data.ResultEx;
import com.mdb.bc.cache.MdbCache;
import com.mdb.bc.utils.ObjectUtil;
import com.mdb.open.common.enums.TradeOpenRetCodeEnum;
import com.mdb.open.common.enums.content.ChannelCodeEnum;
import com.mdb.open.trade.common.MdbDataSource;
import com.mdb.open.trade.config.MdbContentProperties;
import com.mdb.open.trade.domain.dto.content.CommonUploadDto;
import com.mdb.open.trade.domain.po.content.Account;
import com.mdb.open.trade.domain.po.content.FileInfo;
import com.mdb.open.trade.domain.po.content.FileType;
import com.mdb.open.trade.domain.vo.content.AccountVo;
import com.mdb.open.trade.domain.vo.content.InnerUploadVo;
import com.mdb.open.trade.service.content.AccountService;
import com.mdb.open.trade.service.content.FileInfoService;
import com.mdb.open.trade.service.content.FileTypeService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * @author liuyi
 * @date 2019/08/29
 **/
@Log4j2
@Service
@DS(MdbDataSource.CONTENT)
public class ContentFacade {

    @Autowired
    private FileTypeService fileTypeService;
    @Autowired
    private FileInfoService fileInfoService;
    @Autowired
    private AccountService accountService;

    @Autowired
    private MdbContentProperties contentProperties;

    public FileInfo getByFileNo(String fileNo) {
        return fileInfoService.getByFileNo(fileNo);
    }

    public ResultEx<AccountVo> getAccountByAccountId(String accountId) {
        Account account = accountService.getByAccountId(accountId);
        if (ObjectUtil.isEmpty(account)) {
            return ResultEx.ok();
        }
        AccountVo accountVo = new AccountVo();
        accountVo.setId(account.getId());
        accountVo.setAccountId(account.getAccountId());
        accountVo.setAccountName(account.getAccountName());
        accountVo.setSecret(account.getSecret());
        accountVo.setStatus(account.getStatus());
        accountVo.setType(account.getType());
        accountVo.setCreateTime(account.getCreateTime());
        accountVo.setCreateUserName(account.getCreateUserName());
        accountVo.setUpdateTime(account.getUpdateTime());
        accountVo.setOptUserName(account.getOptUserName());

        return ResultEx.ok(accountVo);
    }

    public ResultEx<InnerUploadVo> upload(MultipartFile uploadFile, CommonUploadDto uploadDto) {
        String app = uploadDto.getApp();
        String userId = uploadDto.getUserId();

        FileType fileType = fileTypeService.getByFileType(uploadDto.getFileType());
        if (ObjectUtil.isEmpty(fileType)) {
            return ResultEx.makeResult(TradeOpenRetCodeEnum.FILE_TYPE_NOT_DEFINE);
        }
        String bizType = fileType.getBizType();

        String bizKey = ObjectUtil.isEmpty(uploadDto.getBizKey()) ? userId : uploadDto.getBizKey();
        if (ObjectUtil.isEmpty(bizKey)) {
            bizKey = app;//未登录异常情况
        }

        //文件上传
        try {
            if (ObjectUtil.isEmpty(uploadFile)) {
                return ResultEx.fail();
            }
            //大小限制
            long size = uploadFile.getSize();
            if (size > fileType.getMaxSize() * FileUtils.ONE_KB) {
                return ResultEx.makeResult(TradeOpenRetCodeEnum.CE_OVER_SIZE);
            }
            if (size == 0) {
                return ResultEx.makeResult(TradeOpenRetCodeEnum.CE_NOT_ALLOWED_EMPTY);
            }

            String originalFilename = uploadFile.getOriginalFilename();
            String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            if (ObjectUtil.isEmpty(suffix)) {
                return ResultEx.makeResult(TradeOpenRetCodeEnum.FILE_TYPE_NOT_ALLOWED);
            }
            //文件后缀限制
            //增加后缀
            if (!fileType.getTypeLimit().contains(suffix.toLowerCase())) {
                return ResultEx.makeResult(TradeOpenRetCodeEnum.FILE_TYPE_NOT_ALLOWED);
            }

            String fileMd5HexStr = DigestUtils.md5Hex(uploadFile.getInputStream());//32位
            String fileNo = fileMd5HexStr;
            if (ObjectUtil.isNotEmpty(uploadDto.getSignature())) {
                fileNo = DigestUtils.md5Hex(uploadDto.getSignature() + fileMd5HexStr + DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN));
            }

            //检查fileNo是否存在，如果已存在则直接返回fileNo
            FileInfo checkFileInfo = this.getByFileNo(fileNo);
            if (ObjectUtil.isNotEmpty(checkFileInfo)) {
                InnerUploadVo uploadVo = new InnerUploadVo();
                uploadVo.setFileNo(checkFileInfo.getFileNo());
                uploadVo.setFile(checkFileInfo.getFileUri());
//                uploadVo.setFileUrl(contentProperties.getBaseUrl() + File.separator + fileNo + "." + suffix);
                return ResultEx.ok(uploadVo);
            }

            //文件路径
            String filePath = contentProperties.getUploadRootDir()
                    + File.separator + bizKey
                    + File.separator + app
                    + File.separator + bizType
                    + File.separator + fileType.getFileType()
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE)
                    + File.separator + fileNo;
            //增加后缀
            filePath = filePath + "." + suffix;

            File file = new File(filePath);
            if (!file.exists()) {
                //创建文件及父目录
                FileUtils.forceMkdirParent(file);
            }
            //保存文件
            uploadFile.transferTo(file);

            //保存文件信息到数据库
            FileInfo fileInfo = new FileInfo();
            fileInfo.setFileNo(fileNo);
            fileInfo.setBizKey(bizKey);
            fileInfo.setFileType(fileType.getFileType());
            fileInfo.setBizType(bizType);
            fileInfo.setFileName(originalFilename);
            fileInfo.setSuffix(suffix);
            fileInfo.setSize(uploadFile.getSize());
            fileInfo.setFileUri(filePath);
            fileInfo.setAppCode(app);
            fileInfo.setBizKey(userId);
            fileInfo.setChannelCode(ChannelCodeEnum.NAS.getValue());
            boolean saveResult = fileInfoService.save(fileInfo);

            if (!saveResult) {
                return ResultEx.fail();
            }

            InnerUploadVo uploadVo = new InnerUploadVo();
            uploadVo.setFileNo(fileInfo.getFileNo());
//            uploadVo.setFileUrl(contentProperties.getBaseUrl() + File.separator + fileNo + "." + suffix);
            uploadVo.setFile(fileInfo.getFileNo());
//
//            //根据fileType生成临时url，放入redis
//            List<String> tempFileType = contentProperties.getTmpFileType();
//            if (ObjectUtil.isNotEmpty(tempFileType) && tempFileType.contains(uploadDto.getFileType())) {
//                uploadVo.setFile("tmp" + File.separator + fileNo + "." + suffix);
//                //fileNo: fileInfo
//                mdbCache.setEx(contentProperties.getTmpFileCacheKeyBase() + fileNo, fileNo, contentProperties.getTmpFileTime(), TimeUnit.MINUTES);
//            }

            return ResultEx.ok(uploadVo);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件上传失败，参数：{}, 失败原因：{}", JSON.toJSONString(uploadDto), e.getMessage());
            return ResultEx.fail();
        }
    }

}
